package com.geline.mybatisplus.service;

import com.geline.mybatisplus.context.ExtractAfterThreadLocal;
import com.geline.mybatisplus.context.ExtractTableThreadLocal;
import com.geline.mybatisplus.domain.ExtractEntity;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 批量处理字段回填
 *
 * @author mx
 * @date 2025/8/27
 */
@Slf4j
public class EasyExtractService {
    private ExtractAfterThreadLocal afterThreadLocal;
    private ExtractTableThreadLocal tableThreadLocal;
    private EasyExtractHandler easyExtractHandler;

    public EasyExtractService(ExtractAfterThreadLocal afterThreadLocal, ExtractTableThreadLocal tableThreadLocal, EasyExtractHandler easyExtractHandler){
        this.afterThreadLocal = afterThreadLocal;
        this.tableThreadLocal = tableThreadLocal;
        this.easyExtractHandler = easyExtractHandler;
    }

    private Map<String, Integer> countMap = new HashMap<>();

    /**
     * 批量处理字段回填
     * @param maxLevel 最大回填层级
     */
    public void autoFillExtract(int maxLevel) {
        for(int i=0; i<maxLevel; i++){
            autoFillExtractTable();// 自动填充字段@ExtractCount, @ExtractSum, @ExtractKey, @ExtractStatus
            autoFillExtractAfter();// 自动填充字段@ExtractAfter

            //调用第2次
            autoFillExtractTable();
            autoFillExtractAfter();

            //调用第3次（最多支持3层回填字段）
            autoFillExtractTable();
            autoFillExtractAfter();
        }
    }

    //自动回填属性
    public void autoFillExtractAfter() {
        Map<String, Object> map = afterThreadLocal.getMap();
        if(map!=null && !map.isEmpty()){
            List<String> list = new ArrayList<>(map.keySet());
            Map<String, List<Object>> tableMap = new HashMap<>();
            //处理 @ExtractAfter 回填复杂计算字段:如毛利
            for(String key : list) {
                Integer number = countMap.get(key);
                if(number== null){
                    countMap.put(key, 1);
                }else if(number<2){
                    countMap.put(key, number+1);
                }else {
                    log.error("@ExtractAfter 发现递归更新自己，立即跳出 key = {}", key);
                    countMap.remove(key);
                    break;
                }
                String[] split = key.split(":");
                String targetTable = split[0];
                tableMap.putIfAbsent(targetTable, new ArrayList<>());
                Object entity = map.remove(key);
                tableMap.get(targetTable).add(entity);
            }
            for(String targetTable : tableMap.keySet()){
                log.debug(">>>> targetTable = {}", targetTable);
                easyExtractHandler.fillExtractAfter(tableMap.get(targetTable));
            }

            //递归执行: 处理@ExtractAfter后可能出现新的线程变量
            autoFillExtractAfter();
        }
    }

    //自动回填属性
    public void autoFillExtractTable() {
        Map<String, ExtractEntity> map = tableThreadLocal.getMap();
        if(map!=null && !map.isEmpty()){
            List<String> list = new ArrayList<>(map.keySet());
            log.debug(">>>> autoFillExtractTable keys = {}", list);
            //处理 @ExtractKey 回填当前表字段
            for(String key : list) {
                Integer count = countMap.get(key);
                if(count== null){
                    countMap.put(key, 1);
                }else if(count<2){
                    countMap.put(key, count+1);
                }else {
                    log.warn("@ExtractTable 发现递归更新自己，立即跳出 key = {}", key);
                    countMap.remove(key);
                    break;
                }
                ExtractEntity object = map.remove(key);
                easyExtractHandler.handleExtractTable(object.getEntity(), object.getSourceTable());
            }

            //递归执行: 处理 @ExtractCount @ExtractSum @ExtractKey后可能出现新的线程变量
            autoFillExtractTable();
        }
    }

    public void close() {
        afterThreadLocal.remove();
        log.debug(">>>> remove afterThreadLocal");

        tableThreadLocal.remove();
        log.debug(">>>> remove tableThreadLocal");
    }
}
